package am.ik.cl.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.armedbear.lisp.Stream;
import org.armedbear.lisp.Symbol;

@SuppressWarnings("serial")
public class AbclServlet extends HttpServlet {
    private String encoding = "UTF-8"; // default
    private String lispDir = "/WEB-INF/lisp"; // default
    private static final String ENCODING_KEY = "encoding";
    private static final String LISP_DIR_KEY = "lisp.dir";
    private final ScriptEngine engine;
    private final String STANDARD_OUTPUT_NAME = "*standard-output*";
    private final String REQUEST_NAME = "*request*";
    private final String RESPONSE_NAME = "*response*";
    private final String ROOT_DIR_NAME = "*web-context-root-dir*";
    private final String LISP_EXTENSION = "lisp";

    public AbclServlet() {
        engine = new ScriptEngineManager().getEngineByExtension(LISP_EXTENSION);
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        String encoding = config.getInitParameter(ENCODING_KEY);
        String lispDir = config.getInitParameter(LISP_DIR_KEY);
        if (encoding != null && !encoding.isEmpty()) {
            this.encoding = encoding;
        }
        if (lispDir != null && !lispDir.isEmpty()) {
            this.lispDir = lispDir;
        }
    }

    @Override
    public void service(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        res.setContentType("text/html; charset=" + encoding);
        String path = req.getServletPath();
        InputStream in = getServletContext()
                .getResourceAsStream(lispDir + path);
        engine.put(STANDARD_OUTPUT_NAME, new Stream(res.getOutputStream(),
                Symbol.CHARACTER, Symbol.internKeyword(encoding)));
        engine.put(REQUEST_NAME, req);
        engine.put(RESPONSE_NAME, res);
        if (lispDir.startsWith("/")) {
            engine.put(ROOT_DIR_NAME, lispDir.substring(1));
        } else {
            engine.put(ROOT_DIR_NAME, lispDir);
        }
        if (in != null) {
            try {
                engine.eval(new InputStreamReader(in));
            } catch (ScriptException e) {
                throw new ServletException(e);
            }
        } else {
            res.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }
}
